package com.spring.nio.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.spring.nio.common.BasicConstant;
import com.spring.nio.common.EPlatform;
import com.spring.nio.common.OSinfo;
import com.spring.nio.core.http.HttpContext;
import com.spring.nio.core.http.HttpRequest;
import com.spring.nio.core.http.HttpResponse;
import com.spring.nio.core.http.model.RequestData;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author: spring
 * @Date: 2019/9/7 16:02
 * @Pacage_name: com.spring.nio.util
 * @Project_Name: nio-client
 * @Description:    Http请求解析工具
 */

@Slf4j
public class HttpUtil {

    public static RequestData parseHttpRequest(StringBuffer request, HttpRequest httpRequest, HttpResponse httpResponse) {
        RequestData requestData = null;
        HttpUtil.analysisHttpData(request, httpRequest, httpResponse);
        log.info("[" + LocalTime.formatDate(LocalDateTime.now()) + "] HttpUtil | --> 客户端请求信息, request = {}", httpRequest.toString());

        if(!StringUtils.equals("", httpRequest.getBodyData())) {
            return JSON.parseObject(BasicUtil.replaceBlank(httpRequest.getBodyData()), RequestData.class);
        } else {
            HttpContext.ResponseData responseData = httpResponse.new ResponseData();
            responseData.setCode("101");
            responseData.setMessage("请求body不能为空,解析失败");
            String data = JSON.toJSONString(responseData);
            httpResponse.setBodyData(data);
            httpResponse.getHeaderEntry().setHeader(HttpContext.HttpParamEnum.CONTENT_LENGTH.getParam(), String.valueOf(data.length()));
        }

        return requestData;
    }

    /**
     * 解析RequestData
     * @param requestData
     * @param httpRequest
     * @param httpResponse
     *
     *      核心解析方法 返回解析完成的httpRequest 和 HttpResponse对象,\r 回车(回车到行首) \n 换行(换到下一行),windows \r\n：表示回车回到首行+换行
     * */
    public static void analysisHttpData(StringBuffer requestData, HttpRequest httpRequest, HttpResponse httpResponse) {
        // 不同操作系统\r\n处理方式不同
        if(OSinfo.getOSname().toString().equals(EPlatform.Windows.toString())) {
            analysisWindows(requestData, httpRequest, httpResponse);
        } else {
            analysisUnix(requestData, httpRequest, httpResponse);
        }
    }

    /**
     * windows平台解析
     * @param requestData
     * @param httpRequest
     * @param httpResponse
     * */
    private static void analysisWindows(StringBuffer requestData, HttpRequest httpRequest, HttpResponse httpResponse) {
        String httpData = requestData.toString();;

        String[] strData = httpData.split("\r\n");
        if(null != strData && strData.length > 0) {
            for (int i = 0; i < strData.length; i++) {
                // 请求头行
                if(i == 0) {
                    httpRequest.setRequestHeader(strData[i]);
                } else if(i == (strData.length - 1)) {
                    httpRequest.setBodyData(strData[i].replaceAll(" ", ""));
                } else {
                    httpRequest.getHeaderEntry().setHeader(strData[i].split(": ")[0], strData[i].split(": ")[1]);
                }
            }
        }

        // 装饰响应类
        decorateHttpResponse(httpResponse);
    }

    /**
     * MacOSX或linux平台解析HTTP请求
     * @param requestData
     * @param httpRequest
     * @param httpResponse
     * */
    private static void analysisUnix(StringBuffer requestData, HttpRequest httpRequest, HttpResponse httpResponse) {
        String httpData = requestData.toString();;

        String[] strData = httpData.split("\r\n");
        log.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] HttpUtil | --> 接收到http请求: --> ");
        if(null != strData && strData.length > 0) {
            for (int i = 0; i < strData.length; i++) {
                if(StringUtils.isBlank(strData[i])) {
                    continue;
                }
                // 请求头行
                if(i == 0) {
                    httpRequest.setRequestHeader(strData[i]);
                } else if(i == (strData.length - 1)) {
                    httpRequest.setBodyData(strData[i].replaceAll(" ", ""));
                } else {
                    httpRequest.getHeaderEntry().setHeader(strData[i].split(": ")[0], strData[i].split(": ")[1]);
                }
            }
        }

        // 装饰响应类
        decorateHttpResponse(httpResponse);
    }

    /**
     * 装饰HttpResponse响应类
     * @param httpResponse
     * */
    private static void decorateHttpResponse(HttpResponse httpResponse) {
        httpResponse.setRequestHeader("HTTP/1.1 200 OK");
        HttpContext.HeaderEntry headerEntry = httpResponse.getHeaderEntry();
        headerEntry.setHeader(HttpContext.HttpParamEnum.SERVER.getParam(), "Nio-Client/1.0");
        headerEntry.setHeader(HttpContext.HttpParamEnum.CONTENT_TYPE.getParam(), "application/json; charset=UTF-8");
        headerEntry.setHeader(HttpContext.HttpParamEnum.CONTENT_LENGTH.getParam(), "0");
        headerEntry.setHeader(HttpContext.HttpParamEnum.DATE.getParam(), HttpContext.sdf.format(new Date()));
        httpResponse.setBodyData("");
    }
}
